/**author:yebinx email:yebinx@21cm.com*/
export default class MathTool{
    public static getTwoPointDist(x1:number,y1:number,x2:number,y2:number){
        return Math.sqrt(Math.pow(x2-x1,2)+Math.pow(y2-y1,2));
    }


    /** rect结构 rect.a,rect.b,rect.c,rect.d 属性含x,y*/
    public static pointInRect(x:number,y:number,rect:any){
        let a = (rect.b.x - rect.a.x)*(y - rect.a.y) - (rect.b.y - rect.a.y)*(x - rect.a.x);
        let b = (rect.c.x - rect.b.x)*(y - rect.b.y) - (rect.c.y - rect.b.y)*(x - rect.b.x);
        let c = (rect.d.x - rect.c.x)*(y - rect.c.y) - (rect.d.y - rect.c.y)*(x - rect.c.x);
        let d = (rect.a.x - rect.d.x)*(y - rect.d.y) - (rect.a.y - rect.d.y)*(x - rect.d.x);
        if((a > 0 && b > 0 && c > 0 && d > 0) || (a < 0 && b < 0 && c < 0 && d < 0)) {
            return true;
        }
        return false;
    }
    /**根据两点返回直接方程式的斜率和截距*/
    public static getLineMethodParam(x1:number,y1:number,x2:number,y2:number){
        let k=0;
        if(x2 != x1)k=(y2-y1)/(x2-x1)
        let b = y2 - k * x2;
        return {k:k,b:b}
    }
	
	  /**根据一个点和角度返回直接方程式的斜率和截距*/
	public static getLineMethodParam2(x1:number,y1:number,_angle:number){
		let k = Math.tan(_angle);
		//let y1 = k* x1  + b ;
		let b = y1- k* x1;
		​return 	{k:k,b:b}
		
	}

     /**求点到直线的距离*/
    public static getPointDistLine(x1:number,y1:number,k:number,b:number){
        let tdis = Math.abs(k*x1-y1+b)/Math.sqrt(k*k+1);
        return tdis;
    }
    public static getAngleByTwoPoint(x1:number,y1:number,x2:number,y2:number){
        let tx=x2-x1;
        let ty=y2-y1;
        let ta=Math.atan2(ty,tx);
        let tangle=ta*180/Math.PI;
        return tangle;
    }

    public static getRadinasByTwoPoint(x1:number,y1:number,x2:number,y2:number){
        let tx=x2-x1;
        let ty=y2-y1;
        let ta=Math.atan2(ty,tx);
        return ta;
    }

      /**
     * @method 弧度转角度
     * @param {number} angle 
     * @return {number}
     */
    public static radianToAngle(_r: number): number {
        return _r * 180/Math.PI;
    }

      /**
     * @method 角度转弧度
     * @param {number} angle 
     * @return {number}
     */
    public static angleToRadian(angle: number): number {
        return angle * Math.PI / 180;
    }
    /**把角度转换成360以内*/
    public static getAngleIn360(_angle:number){
        let tmo = _angle%360;
        if(tmo>=0)return tmo;
        return 360+tmo;
    }

    public static getSpeedByTwoPoint(_x1:number,_y1:number,_x2:number,_y2:number,_maxSpeed:number=1){
        let trad = this.getRadinasByTwoPoint(_x1,_y1,_x2,_y2);
        let tdist = this.getTwoPointDist(_x1,_y1,_x2,_y2);
        if(tdist>_maxSpeed)tdist=_maxSpeed;
        return {x:tdist*Math.cos(trad),y:tdist*Math.sin(trad)};
    }

    /**直线是否穿过圆*/
    public static lineCrossCircle(k:number,b:number,x:number,y:number,r:number){
        let tdist = this.getPointDistLine(x,y,k,b);
        return tdist<r;
    }

    /**两段直线是否相交 aa,bb一段直线cc,dd一段直线*/
    public static toLineIsCross(aa,bb,cc,dd){
        let delta:number = this.determinant(bb.x-aa.x, cc.x-dd.x, bb.y-aa.y, cc.y-dd.y);  
        if ( delta<=(1e-6) && delta>=-(1e-6) )  // delta=0，表示两线段重合或平行  
        {  
            return false;  
        }  
        let namenda:number = this.determinant(cc.x-aa.x, cc.x-dd.x, cc.y-aa.y, cc.y-dd.y) / delta;  
        if ( namenda>1 || namenda<0 )  
        {  
            return false;  
        }  
        let miu:number = this.determinant(bb.x-aa.x, cc.x-aa.x, bb.y-aa.y, cc.y-aa.y) / delta;  
        if ( miu>1 || miu<0 )  
        {  
            return false;  
        }  
        return true;
    }

    private static determinant(v1:number,v2:number,v3:number,v4:number):number{
        return (v1*v3-v2*v4);  
    }

     /**
     * 计算二次贝塞尔点。t 0到1为起始点到终点时间
     */
    public static getBerizPoint(t: number, p1,p2,p3) {
        //二次贝塞尔曲线公式 
        let lineX: number = Math.pow((1 - t), 2) * p1.x + 2 * t * (1 - t) * p2.x + Math.pow(t, 2) * p3.x;
        let lineY: number = Math.pow((1 - t), 2) * p1.y + 2 * t * (1 - t) * p2.y + Math.pow(t, 2) * p3.y;
       return [lineX, lineY];
    }

    public static isIn(_value:number,a:number,b:number){
        return _value>=a && _value<=b;
    }

    public static getStrColorToRbg(_color:string){
        let tarr=[];
        for(let i=1;i<_color.length;i +=2){
            //console.log(_color.slice(i,i+2));
            tarr.push(parseInt("0x"+_color.slice(i,i+2))/255)
        }
        return tarr;
    }

    

     //像素点对比
     public static pixelsContrast(pixels:Uint8Array, pixels2:Uint8Array, tmplw, tmplh):number {            
        var tw = tmplw || 8,  // 模板宽度                
        th = tmplh || 8;  // 模板高度
        //console.log(pixels,pixels2);
        pixels = this.pixelsToBinary(pixels, 1);
        pixels2 = this.pixelsToBinary(pixels2, 1);
        //console.log("2",pixels,pixels2);
        var similar:number=0, total:number=0, more:number=0;
        let tlen = tw*th/2;
        for (var i = 0; i < tlen; i++) {
            if(pixels[i]==0 && pixels2[i]==0) continue;//排除空白部分
            if(pixels[i]==0 && pixels2[i]==1) more++;//多出部分
            else if(pixels[i]==1) {
                total++;
                if(pixels2[i]==1) similar++;//相同部分
            }
        }
        var result:number = (( similar - more) / total) * 100;
        if(result<0)result=0;
        result=Math.floor(result);
        if(result>97)result=100;
       // console.log("像素对比结果=","总数：",total,",相似：",similar,",多余:",more,",相似度:",result,pixels,pixels2);
        return result;           
    }

    // 像素数据，二值化闵值（0-255），返回二值化后序列
    private static pixelsToBinary(pixels:Uint8Array, value) :Uint8Array{ 
        let tount:number=8;           
        var r, g, b, g, avg = 0, len = pixels.length,saLength=len/tount,saIndex=0;
        var sa:Uint8Array=new Uint8Array(saLength);
        if(!value){
            for (var i = 0; i < len; i += tount) {                
                avg += (.299 * pixels[i] + .587 * pixels[i + 1] + .114 * pixels[i + 2]);            
            }
            avg /= (len / 4);
            value = avg;
        }
        let tcount:number=0;
        for (var i = 0; i < len; i += tount) {    
            //计算图像的灰度值,公式为：Gray = R*0.299 + G*0.587 + B*0.114           
            r = .299 * pixels[i], 
            g = .587 * pixels[i + 1], 
            b = .114 * pixels[i + 2];                
            
            if ((r + g + b) >= value) {  
                //g=255;                      
                sa[saIndex++]=1;  
                tcount++;                  
            } else { 
                //g=0;                       
                sa[saIndex++]=0;                 
            }                    
        }
        console.log("tcount:"+tcount);
        return sa;               
    }

    /**获取竖方向由下往上的折线信息,按laya的坐标系计算*/
    public static getZheXianByV(_sx:number,_sy:number,_ex:number,_ey:number,_minx:number,_maxx:number,_minY:number=0,_stepLen:number=10){
        let trad=this.getRadinasByTwoPoint(_sx,_sy,_ex,_ey);
        let tangel = this.getAngleByTwoPoint(_sx,_sy,_ex,_ey);
        let currP:Laya.Point=new Laya.Point(_sx,_sy);
        let tp:Laya.Point=new Laya.Point(_sx,_sy);
        let tindex:number=0;
        let tspointIndexs=[tindex];//精简点
        let tpoints=[tp];//详细点
        let tcurrLen=_stepLen;
        let tx=currP.x+tcurrLen*Math.cos(trad);
        let ty=currP.y+tcurrLen*Math.sin(trad);
        tp = new Laya.Point(tx,ty);
        tindex++;
        tspointIndexs.push(tindex);
        tpoints.push(tp);
        while(ty>_minY){
            tindex++;
            tcurrLen += _stepLen;
            tx=currP.x+tcurrLen*Math.cos(trad);
            ty=currP.y+tcurrLen*Math.sin(trad);
            if(tx<=_minx){
                trad=this.getRadinasByTwoPoint(tx,ty,_sx,ty-(currP.y-ty));
                tx=_minx;
                currP.setTo(tx,ty);
                tcurrLen=0;
                tspointIndexs.push(tindex);
            }else if(tx>=_maxx){
                trad=this.getRadinasByTwoPoint(tx,ty,_sx,ty-(currP.y-ty));
                tx=_maxx;
                currP.setTo(tx,ty);
                tcurrLen=0;
                tspointIndexs.push(tindex);
            }
            tp=new Laya.Point(tx,ty);
            tpoints.push(tp);
            if(tindex>1000)break;
        }
        
        if(tspointIndexs.indexOf(tindex)<0)tspointIndexs.push(tindex);
        return {point:tpoints,spointIndex:tspointIndexs,angle:tangel};
    }
}